$(document).ready(function() {
    /**************** methods and constants ****************/

    /**
     * Marker class for highlighting query results.
     */
    const highlight_marker = "info";

    /**
     * Default record for add new row of data.
     */
    const default_record = {num: 1000, name: "", sex: "男", pass: "", age: 1, birth: "2019-01-01"};

    /**
     * Add new data record to the table.
     * @param record single row of data, including: num, name, sex, pass, age, birth.
     */
    function addRow(record) {
        // construct table row
        let row = document.createElement("tr");

        // construct checkbox
        let checkboxCell = document.createElement("td");
        let checkbox = document.createElement("input");
        checkbox.setAttribute("type", "checkbox");
        checkboxCell.appendChild(checkbox);
        row.appendChild(checkboxCell);
        
        // construct data cells
        for (let prop of ["num", "name", "sex", "pass", "age", "birth"]) {
            let cell = document.createElement("td");
            cell.textContent = String(record[prop]);
            row.appendChild(cell);
        }

        // append row
        $("#table-data").append(row);
    }

    /**
     * Removes all the checked rows.
     */
    function remove() {
        if (window.confirm("是否要删除选中数据")) {
            $("#table-data tr")
                .has("td:first-child > :checked")
                .fadeOut('slow', function() {
                    $(this).remove();
                });
        }
    }

    /**
     * Query by testing num and name equality, and mark highlight.
     */
    function query() {
        // clear all the marks, avoid touching all the DOM nodes.
        $("#table-data tr")
            .removeClass(highlight_marker);

        let num = $("#query-num").val().trim();
        let name = $("#query-name").val().trim();
        $("#table-data tr").filter(function(idx, elem) {
            let inum = $("td:nth-child(2)", elem).text().trim();
            let iname = $("td:nth-child(3)", elem).text().trim();
            if (num && name) {
                return inum === num && iname === name;
            } else if (num) {
                return inum === num;
            } else if (name) {
                return iname === name;
            } else {
                return false;
            }
        }).addClass(highlight_marker);
    }

    /**
     * Show the modal with initial values.
     * @param title modal title.
     * @param record single row of data.
     */
    function showModal(title, record, submit) {
        // change title
        $("#modal-title").text(title);

        // set initial values
        $("#modal-num").val(record.num);
        $("#modal-name").val(record.name);
        $("#modal-sex input[type=radio]").removeAttr("checked");
        if (record.sex !== "女") {
            $("#modal-sex-male").prop("checked", true);
        } else {
            $("#modal-sex-female").prop("checked", true);
        }
        $("#modal-pass").val(record.pass);
        $("#modal-age").val(record.age);
        $("#modal-birth").val(record.birth);

        // bind submit event
        $("#modal-submit").unbind("click");
        $("#modal-submit").click(submit);

        // show modal
        $('#modal').modal('show');
    }

    /**
     * Read single row of data from the modal.
     */
    function readModal() {
        return {
            num: $("#modal-num").val(),
            name: $("#modal-name").val(),
            sex: $("#modal-sex-female").prop("checked") ? "女" : "男",
            pass: $("#modal-pass").val(),
            age: $("#modal-age").val(),
            birth: $("#modal-birth").val()
        };
    }

    /**
     * Add single row of data from the modal.
     */
    function add() {
        showModal("添加数据", default_record, function() {
            let record = readModal();
            if (record.num && record.name && record.sex && record.pass && record.age > 0 && record.birth) {
                setTimeout(function() { addRow(record); }, 500);
                $('#modal').modal('hide');
            } else {
                alert("数据必须全部正确填写");
            }
        });
    }

    /**
     * Get data in the first selected row.
     */
    function getSelected() {
        let cells = $("#table-data tr")
            .has("td:first-child > :checked")
            .first()
            .find("td:not(:first)");
        return {
            num: cells.get(0).textContent.trim(),
            name: cells.get(1).textContent.trim(),
            sex: cells.get(2).textContent.trim(),
            pass: cells.get(3).textContent.trim(),
            age: cells.get(4).textContent.trim(),
            birth: cells.get(5).textContent.trim()
        };
    }

    /**
     * Set data in the first selected row.
     */
    function setSelected(record) {
        let cells = $("#table-data tr")
            .has("td:first-child > :checked")
            .first()
            .find("td:not(:first)");
        cells.eq(0).text(record.num);
        cells.eq(1).text(record.name);
        cells.eq(2).text(record.sex);
        cells.eq(3).text(record.pass);
        cells.eq(4).text(record.age);
        cells.eq(5).text(record.birth);
    }

    /**
     * Edit the first selected row of data.
     */
    function edit() {
        let selected = $("#table-data tr > td:first-child > :checked").length;
        if (selected < 1) {
            alert("请选择数据");
            return;
        } else if (selected > 1) {
            alert("选择多条数据时，只能编辑第一条");
        }

        showModal("编辑数据", getSelected(), function() {
            let record = readModal();
            if (record.num && record.name && record.sex && record.pass && record.age > 0 && record.birth) {
                setSelected(record);
                $('#modal').modal('hide');
            } else {
                alert("数据必须全部正确填写");
            }
        });
    }

    /**************** setup states ****************/

    // table initialization
    addRow({num: 1001, name: "张三", sex: "女", pass: "1234", age: 29, birth: "1991-01-01"});
    addRow({num: 1002, name: "李四", sex: "男", pass: "1234", age: 28, birth: "1992-02-02"});
    addRow({num: 1003, name: "王五", sex: "女", pass: "1234", age: 27, birth: "1992-03-03"});
    addRow({num: 1004, name: "赵六", sex: "女", pass: "1234", age: 25, birth: "1992-04-04"});

    // event handlers
    $("#btn-remove").click(remove);
    $("#btn-query").click(query);
    $("#btn-add").click(add);
    $("#btn-edit").click(edit);
});
